package com.xbongbong.workflow.service.strategy.data.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.FundAccountFlowTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PaymentSheetTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.enums.SheetTypeEnum;
import com.xbongbong.paas.enums.TaskTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.log.constant.CrmLogMemoConstant;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.pojo.CreditCardBillInfoPojo;
import com.xbongbong.paas.pojo.dto.CreditCardBillDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.pro.constant.CustomerCommunicateConstant;
import com.xbongbong.pro.constant.SymbolConstant;
import com.xbongbong.pro.customercommunicate.pojo.dto.CustomerDynamicAddDTO;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.pro.message.constant.PaymentPushConstant;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.help.PushHelper;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.MessageRabbitMqDTO;
import com.xbongbong.pro.message.service.MessageService;
import com.xbongbong.pro.paymentsheet.pojo.dto.PaymentSheetSaveDTO;
import com.xbongbong.pro.sheet.pojo.SheetAttrPojo;
import com.xbongbong.pro.sheet.pojo.vo.HandleLinkInfoVO;
import com.xbongbong.pro.team.pojo.TeamSavePojo;
import com.xbongbong.pro.workflow.enums.WorkflowOperateEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.domain.entity.DistributorBaseInfoEntity;
import com.xbongbong.saas.domain.entity.FundAccountFlowEntity;
import com.xbongbong.saas.domain.entity.PaymentSheetUserEntity;
import com.xbongbong.saas.domain.entity.ext.PaymentSheetEntityExt;
import com.xbongbong.saas.enums.CreditCardBillTypeEnum;
import com.xbongbong.saas.enums.ProjectLogEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.PaymentSheetDistributorEnum;
import com.xbongbong.saas.enums.business.PaymentSheetEnum;
import com.xbongbong.saas.help.FundHelp;
import com.xbongbong.saas.help.SaasCreditHelper;
import com.xbongbong.saas.help.SaasCustomerStatementHelper;
import com.xbongbong.saas.help.SaasPaymentHelper;
import com.xbongbong.saas.help.SaasPaymentSheetHelper;
import com.xbongbong.saas.help.SaasRefundHelper;
import com.xbongbong.saas.help.workflow.ContractHelp;
import com.xbongbong.saas.help.workflow.PayAndPaymentSheetHelp;
import com.xbongbong.saas.model.FundAccountFlowModel;
import com.xbongbong.saas.model.PaasFormSubDataModel;
import com.xbongbong.saas.model.PaymentModel;
import com.xbongbong.saas.model.PaymentSheetModel;
import com.xbongbong.saas.model.PaymentSheetUserModel;
import com.xbongbong.saas.service.CustomerCommunicateService;
import com.xbongbong.saas.service.PaymentSheetService;
import com.xbongbong.saas.service.toolbox.help.SaasSaveHelper;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.workflow.domain.entity.WorkflowBackupDataEntity;
import com.xbongbong.workflow.model.WorkflowBackupDataModel;
import com.xbongbong.workflow.pojo.Data;
import com.xbongbong.workflow.pojo.WorkflowTransferPOJO;
import com.xbongbong.workflow.service.strategy.data.AbstractWorkflowDataStrategy;
import com.xbongbong.workflow.service.strategy.data.WorkflowDataProcessStrategy;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static java.lang.String.format;
import static java.lang.String.join;

/**
 *
 * @author 魏荣杰
 *
 */
@Service
@Slf4j
public class WorkflowPaymentSheetStrategy extends AbstractWorkflowDataStrategy implements WorkflowDataProcessStrategy {

    private static final Logger LOGGER = LoggerFactory.getLogger(WorkflowPaymentSheetStrategy.class);

    @Resource
    private PaymentSheetModel paymentSheetModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private PayAndPaymentSheetHelp payAndPaymentSheetHelp;
    @Resource
    private WorkflowBackupDataModel workflowBackupDataModel;
    @Resource
    private SaasSaveHelper saasSaveHelper;
    @Resource
    private SaasPaymentHelper saasPaymentHelper;
    @Resource
    private ContractHelp contractHelp;
    @Resource
    private SaasPaymentSheetHelper saasPaymentSheetHelper;
    @Resource
    private PaymentModel paymentModel;
    @Resource
    private FundHelp fundHelp;
    @Resource
    private FundAccountFlowModel fundAccountFlowModel;
    @Resource
    private SaasCustomerStatementHelper saasCustomerStatementHelper;
    @Resource
    private SaasCreditHelper saasCreditHelper;
    @Resource
    private PushHelper pushHelper;
    @Resource
    private UserModel userModel;
    @Resource
    private CustomerCommunicateService customerCommunicateService;
    @Resource
    private MessageService messageService;
    @Resource
    private PaasFormSubDataModel paasFormSubDataModel;
    @Resource
    private SaasRefundHelper saasRefundHelper;
    @Resource
    private PaymentSheetService paymentSheetService;
    @Resource
    private PaymentSheetUserModel paymentSheetUserModel;

    @Override
    public List<Integer> type() {
        return Arrays.asList(XbbRefTypeEnum.PAYMENT_SHEET.getCode(), XbbRefTypeEnum.WRITE_OFF_PREPAYMENT.getCode(), XbbRefTypeEnum.PREPAYMENT.getCode(), XbbRefTypeEnum.RED_PREPAYMENT.getCode(), XbbRefTypeEnum.RED_PAYMENT_SHEET.getCode(), XbbRefTypeEnum.RED_WRITE_OFF_PREPAYMENT.getCode(), XbbRefTypeEnum.RED_WRITE_OFF_BALANCE.getCode(), XbbRefTypeEnum.BAD_DEBT.getCode());
    }

    @Override
    public void save(WorkflowTransferPOJO workflowTransferPOJO, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) throws XbbException {
        // 文件柜
        saveDataCabinetFile(workflowTransferPOJO);
        String corpid = workflowTransferPOJO.getCorpid();
        Data pojoData = workflowTransferPOJO.getData();
        Integer subBusinessType = pojoData.getSubBusinessType();
        Long dataId = pojoData.getId();
        JSONObject data = pojoData.getData();
        if (Objects.equals(XbbRefTypeEnum.PAYMENT_SHEET.getCode(), subBusinessType)) {
            //已核销
            workFlowWriteOffSave(workflowTransferPOJO, saasNeedRedundantAttrPojo);
        } else if (Objects.equals(XbbRefTypeEnum.WRITE_OFF_PREPAYMENT.getCode(), subBusinessType)) {
            //预收款核销
            workFlowWriteOffSave(workflowTransferPOJO, saasNeedRedundantAttrPojo);
        } else if (Objects.equals(XbbRefTypeEnum.PREPAYMENT.getCode(), subBusinessType)) {
            //预收款
            workFlowPrepaymentAfterSave(workflowTransferPOJO, saasNeedRedundantAttrPojo);
        } else if (Objects.equals(XbbRefTypeEnum.RED_PREPAYMENT.getCode(), subBusinessType)) {
            //红冲预收款
            workFlowPrepaymentAfterSave(workflowTransferPOJO, saasNeedRedundantAttrPojo);
        } else if (Objects.equals(XbbRefTypeEnum.RED_PAYMENT_SHEET.getCode(), subBusinessType)) {
            //红冲已核销
            workFlowRedAfterSave(workflowTransferPOJO, saasNeedRedundantAttrPojo);
        } else if (Objects.equals(XbbRefTypeEnum.RED_WRITE_OFF_PREPAYMENT.getCode(), subBusinessType)) {
            //红冲预收款核销
            workFlowRedAfterSave(workflowTransferPOJO, saasNeedRedundantAttrPojo);
        } else if (Objects.equals(XbbRefTypeEnum.RED_WRITE_OFF_BALANCE.getCode(), subBusinessType)) {
            //红冲预收款核销(退到余额)
            workFlowRedAfterSave(workflowTransferPOJO, saasNeedRedundantAttrPojo);
        } else if (Objects.equals(XbbRefTypeEnum.BAD_DEBT.getCode(), subBusinessType)) {
            //坏账
            workFlowBadAfterSave(workflowTransferPOJO, saasNeedRedundantAttrPojo);
        }

        //这里需要重置退货退款里面的回款单信息
        Long refundId = saasNeedRedundantAttrPojo.getRefundId();
        if (refundId != null) {
            PaasFormDataEntity paasFormDataEntity = new PaasFormDataEntity();
            paasFormDataEntity.setId(dataId);
            paasFormDataEntity.setSerialNo(data.getString(BasicConstant.SERIAL_NO));
            saasRefundHelper.updateRefundPaymentSheetId(refundId, paasFormDataEntity, corpid);
        }

        // api
        apiHook(workflowTransferPOJO);
        addLinkDataDynamic(workflowTransferPOJO);
        // log
        afterSaveLog(workflowTransferPOJO);
    }

    /**
     * 工作流坏账回款单
     *
     * @param workflowTransferPOJO
     * @param saasNeedRedundantAttrPojo
     */
    private void workFlowBadAfterSave(WorkflowTransferPOJO workflowTransferPOJO, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) throws XbbException {
        Data pojoData = workflowTransferPOJO.getData();
        Integer subBusinessType = pojoData.getSubBusinessType();
        String corpid = workflowTransferPOJO.getCorpid();
        Long dataId = pojoData.getId();
        String userId = workflowTransferPOJO.getUser().getUserId();
        JSONObject newData = pojoData.getData();
        Long formId = pojoData.getFormId();
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
        Integer distributorMark = paasFormExplainEntity.getDistributorMark();
        PaymentSheetEntityExt paymentSheetEntityExt = paymentSheetModel.getByKey(dataId, corpid);

        PaymentSheetTypeEnum paymentSheetTypeEnum = PaymentSheetTypeEnum.getByBusinessType(subBusinessType);
        SheetTypeEnum sheetTypeEnum = paymentSheetTypeEnum.getSheetTypeEnum();
        SheetAttrPojo sheetAttrPojo = new SheetAttrPojo(XbbRefTypeEnum.PAYMENT_SHEET);
        //回款单的实收回款金额
        Double sheetAmount = FastJsonHelper.getDoubleOrDefaultFromFormData(newData, PaymentSheetEnum.AMOUNT.getAttr(), 0D);
        double allAmount = 0D;
        Set<Long> contractIds = new HashSet<>();
        Set<Long> paymentIds = new HashSet<>();
        List<PaymentSheetEntityExt> sonSheetList = null;
        //应收款和合同对应的回款金额
        Map<Long, Double> contractIdToAmount = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, Double> paymentIdToAmount = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

        //处理金额明细
        SaasFormSaveDTO saasFormSaveDTO = new SaasFormSaveDTO();
        saasFormSaveDTO.setExplainMap(explainMap);
        saasFormSaveDTO.setDistributorMark(paasFormExplainEntity.getDistributorMark());
        List<JSONObject> sonPaymentSheetDataList = saasSaveHelper.handleAmountDetail(saasFormSaveDTO, sheetAmount, sheetTypeEnum, sheetAttrPojo, newData, saasNeedRedundantAttrPojo.getAmountDetail(), allAmount, contractIdToAmount, paymentIdToAmount, contractIds, paymentIds);
        //处理应收款并封装要更新的结果：判断已收金额是否已经超过应收款内的未收金额，并把应收款的已收金额增加及更改其回款状态等
        HandleLinkInfoVO paymentLinkInfoVO = saasPaymentHelper.handlePayment(PaymentSheetTypeEnum.BAD_PAYMENT, newData, corpid, paymentIdToAmount, paymentIds);
        List<UpdateDataEntity> updatePayList = paymentLinkInfoVO.getUpdateList();
        //处理合同并封装要更新的结果：判断已收金额是否已经超过合同内的未收金额，并把合同的已收金额增加等
        List<UpdateDataEntity> updateConList = contractHelp.handleContract(distributorMark, PaymentSheetTypeEnum.BAD_PAYMENT, corpid, contractIdToAmount, contractIds);
        //插入回款单子回款单
        sonSheetList = saasPaymentSheetHelper.savePaymentSheetSon(corpid, sonPaymentSheetDataList,  paymentSheetEntityExt, paymentSheetEntityExt.getUuid(), paymentLinkInfoVO);
        //更新应收款/合同
        paymentModel.savePaymentPlan(corpid, updatePayList);
        contractHelp.saveContract(corpid, updateConList, "PaymentSheetServiceImpl.redSave：新建红冲回款单更新合同时失败");
        //按最小纬度进项生成客户对账单
        if (sonSheetList.size() > BasicConstant.ONE) {
            saasCustomerStatementHelper.save(XbbRefTypeEnum.PAYMENT_SHEET.getCode(), explainMap, sonSheetList, distributorMark);
        } else {
            saasCustomerStatementHelper.save(XbbRefTypeEnum.PAYMENT_SHEET.getCode(), explainMap, Arrays.asList(paymentSheetEntityExt), distributorMark);
        }
        //处理回款单团队-必须在团队保存后执行，需要用到回款单的id
        try{
            TeamSavePojo teamSavePojo = new TeamSavePojo(paymentSheetEntityExt, sonSheetList, true, paymentSheetEntityExt, saasNeedRedundantAttrPojo, null, true);
            paymentSheetService.operateSheetTeam(teamSavePojo.getPaymentSheetEntityExt(), teamSavePojo.getSheetList(), teamSavePojo.getIgnoreMainSheet(), teamSavePojo.getNewPaasFormDataEntity(), teamSavePojo.getSaasNeedRedundantAttrPojo(), teamSavePojo.getIsImport(), teamSavePojo.getWorkflowTag());
        }catch (Exception e){
            log.error("处理回款单团队", e);
        }
        if(Objects.equals(DistributorMarkEnum.DISTRIBUTOR.getCode(),distributorMark)) {
            createLogAndMessage(PushTypeEnum.PAYMENT_SHEET_BAD_ADD, newData, corpid, userId, paymentSheetEntityExt, I18nMessageUtil.getMessage(CustomerCommunicateConstant.PAYMENT_SHEET_BAD_CONTRACT), I18nMessageUtil.getMessage(PaymentPushConstant.PAYMENT_SHEET_BAD_ADD_TITLE), I18nMessageUtil.getMessage(PaymentPushConstant.PAYMENT_SHEET_BAD_ADD_CONTENT), distributorMark);
        } else {
            createLogAndMessage(PushTypeEnum.PAYMENT_SHEET_BAD_ADD, newData, corpid, userId, paymentSheetEntityExt, I18nMessageUtil.getMessage(CrmLogMemoConstant.DYNAMIC_USER_PAYMENT_SHEET_BAD_CONTRACT), I18nMessageUtil.getMessage(PaymentPushConstant.PAYMENT_SHEET_BAD_ADD_TITLE), I18nMessageUtil.getMessage(PaymentPushConstant.PAYMENT_SHEET_BAD_ADD_CONTENT), distributorMark);
        }
    }

    /**
     * 工作流红冲已核销、红冲预收款核销、红冲预收款核销(退到余额)回款单
     *
     * @param workflowTransferPOJO
     * @param saasNeedRedundantAttrPojo
     */
    private void workFlowRedAfterSave(WorkflowTransferPOJO workflowTransferPOJO, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) throws XbbException {
        Data pojoData = workflowTransferPOJO.getData();
        Integer subBusinessType = pojoData.getSubBusinessType();
        String corpid = workflowTransferPOJO.getCorpid();
        String userId = workflowTransferPOJO.getUser().getUserId();
        Long dataId = pojoData.getId();
        JSONObject newData = pojoData.getData();
        Long formId = pojoData.getFormId();
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
        Integer distributorMark = paasFormExplainEntity.getDistributorMark();
        PaymentSheetEntityExt paymentSheetEntityExt = paymentSheetModel.getByKey(dataId, corpid);

        PaymentSheetTypeEnum paymentSheetTypeEnum = PaymentSheetTypeEnum.getByBusinessType(subBusinessType);
        SheetTypeEnum sheetTypeEnum = paymentSheetTypeEnum.getSheetTypeEnum();
        SheetAttrPojo sheetAttrPojo = new SheetAttrPojo(XbbRefTypeEnum.PAYMENT_SHEET);
        //回款单的实收回款金额
        Double sheetAmount;
        Double amount;
        boolean redWriteOffBalanceFlag = SheetTypeEnum.onlyWriteOffAmount(paymentSheetTypeEnum.getCode());
        Set<Long> contractIds = new HashSet<>();
        Set<Long> paymentIds = new HashSet<>();
        if (redWriteOffBalanceFlag) {
            //预收款核销，是用的核销金额
            sheetAmount = FastJsonHelper.getDoubleOrDefaultFromFormData(newData, PaymentSheetEnum.WRITE_OFF_AMOUNT.getAttr(), 0D);
        } else {
            sheetAmount = FastJsonHelper.getDoubleOrDefaultFromFormData(newData, PaymentSheetEnum.AMOUNT.getAttr(), 0D);
        }
        amount = Arith.mul(sheetAmount, -1);
        List<PaymentSheetEntityExt> sonSheetList = null;
        //应收款和合同对应的回款金额
        Map<Long, Double> contractIdToAmount = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, Double> paymentIdToAmount = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //处理金额明细
        SaasFormSaveDTO saasFormSaveDTO = new SaasFormSaveDTO();
        saasFormSaveDTO.setExplainMap(explainMap);
        saasFormSaveDTO.setDistributorMark(paasFormExplainEntity.getDistributorMark());
        List<JSONObject> sonPaymentSheetDataList = saasSaveHelper.handleAmountDetail(saasFormSaveDTO, sheetAmount, sheetTypeEnum,
                sheetAttrPojo, newData, saasNeedRedundantAttrPojo.getAmountDetail(), sheetAmount, contractIdToAmount, paymentIdToAmount, contractIds,
                paymentIds);
        //处理应收款并封装要更新的结果：判断已收金额是否已经超过应收款内的未收金额，并把应收款的已收金额增加及更改其回款状态等
        HandleLinkInfoVO paymentLinkInfoVO = saasPaymentHelper.handlePayment(PaymentSheetTypeEnum.RED_WRITE_OFF, newData, corpid, paymentIdToAmount, paymentIds);
        List<UpdateDataEntity> updatePayList = paymentLinkInfoVO.getUpdateList();
        //处理合同并封装要更新的结果：判断已收金额是否已经超过合同内的未收金额，并把合同的已收金额增加等
        List<UpdateDataEntity> updateConList = contractHelp.handleContract(distributorMark, PaymentSheetTypeEnum.RED_WRITE_OFF, corpid, contractIdToAmount, contractIds);
        //插入回款单子回款单
        sonSheetList = saasPaymentSheetHelper.savePaymentSheetSon(corpid, sonPaymentSheetDataList,  paymentSheetEntityExt, paymentSheetEntityExt.getUuid(), paymentLinkInfoVO);
        //更新应收款/合同
        paymentModel.savePaymentPlan(corpid, updatePayList);
        contractHelp.saveContract(corpid, updateConList, "PaymentSheetServiceImpl.redSave：新建红冲回款单更新合同时失败");
        if (redWriteOffBalanceFlag) {
            //核销预收款回款单新建时，减少预收款余额
            saasPaymentSheetHelper.saveByPaymentSheet(paymentSheetEntityExt, distributorMark);
        }else {
            Long addTime = paymentSheetEntityExt.getAddTime();
            Long accountId = FastJsonHelper.getLongOrDefaultFromFormData(newData, PaymentSheetEnum.FUND_ACCOUNT.getAttr(), 0L);
            Long sheetTime = fundHelp.getSheetTime4FundFlow(newData, PaymentSheetEnum.PAYMENT_TIME.getAttr(), explainMap, addTime);
            //账户余额变动
            payAndPaymentSheetHelp.saveByPaymentSheetOrPaySheet(accountId, amount, corpid);
            //流水表日志记录
            FundAccountFlowEntity fundAccountFlowEntity = new FundAccountFlowEntity(corpid, addTime, paymentSheetEntityExt.getCreatorId(), FundAccountFlowTypeEnum.PAYMENT_SHEET.getCode(), dataId, accountId, sheetTime, amount);
            fundAccountFlowModel.insert(fundAccountFlowEntity);
        }
        //按最小纬度进项生成客户对账单
        if (sonSheetList.size() > BasicConstant.ONE) {
            saasCustomerStatementHelper.save(XbbRefTypeEnum.PAYMENT_SHEET.getCode(), explainMap, sonSheetList, distributorMark);
        } else {
            saasCustomerStatementHelper.save(XbbRefTypeEnum.PAYMENT_SHEET.getCode(), explainMap, Arrays.asList(paymentSheetEntityExt), distributorMark);
        }
        //处理回款单团队-必须在团队保存后执行，需要用到回款单的id
        //saasPaymentSheetHelper.handleSheetTeam(newData, corpid, sheetTypeEnum, paymentSheetEntityExt, sonSheetList, false);
        try{
            TeamSavePojo teamSavePojo = new TeamSavePojo(paymentSheetEntityExt, sonSheetList, true, paymentSheetEntityExt, saasNeedRedundantAttrPojo, null, true);
            paymentSheetService.operateSheetTeam(teamSavePojo.getPaymentSheetEntityExt(), teamSavePojo.getSheetList(), teamSavePojo.getIgnoreMainSheet(), teamSavePojo.getNewPaasFormDataEntity(), teamSavePojo.getSaasNeedRedundantAttrPojo(), teamSavePojo.getIsImport(), teamSavePojo.getWorkflowTag());
        }catch (Exception e){
            log.error("处理回款单团队", e);
        }
        if(Objects.equals(DistributorMarkEnum.DISTRIBUTOR.getCode(),distributorMark)) {
            createLogAndMessage(PushTypeEnum.PAYMENT_SHEET_RED_ADD, newData, corpid, userId, paymentSheetEntityExt, I18nMessageUtil.getMessage(CustomerCommunicateConstant.PAYMENT_SHEET_RED_ADD_CONTRACT), I18nMessageUtil.getMessage(PaymentPushConstant.PAYMENT_SHEET_RED_ADD_TITLE), I18nMessageUtil.getMessage(PaymentPushConstant.PAYMENT_SHEET_RED_ADD_CONTENT), distributorMark);
        } else {
            createLogAndMessage(PushTypeEnum.PAYMENT_SHEET_RED_ADD, newData, corpid, userId, paymentSheetEntityExt, I18nMessageUtil.getMessage(CrmLogMemoConstant.DYNAMIC_USER_PAYMENT_SHEET_RED_ADD_CONTRACT), I18nMessageUtil.getMessage(PaymentPushConstant.PAYMENT_SHEET_RED_ADD_TITLE), I18nMessageUtil.getMessage(PaymentPushConstant.PAYMENT_SHEET_RED_ADD_CONTENT), distributorMark);
        }
    }

    /**
     * 预收款、红冲预收款回款单
     *
     * @param workflowTransferPOJO
     * @param saasNeedRedundantAttrPojo
     */
    private void workFlowPrepaymentAfterSave(WorkflowTransferPOJO workflowTransferPOJO, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) throws XbbException {
        Data pojoData = workflowTransferPOJO.getData();
        Integer subBusinessType = pojoData.getSubBusinessType();
        String corpid = workflowTransferPOJO.getCorpid();
        Long dataId = pojoData.getId();
        String userId = workflowTransferPOJO.getUser().getUserId();
        JSONObject dataList = pojoData.getData();
        PaymentSheetEntityExt paymentSheetEntityExt = paymentSheetModel.getByKey(dataId, corpid);
        Long formId = pojoData.getFormId();
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
        Integer distributorMark = paasFormExplainEntity.getDistributorMark();
        PaymentSheetTypeEnum paymentSheetTypeEnum = PaymentSheetTypeEnum.getByBusinessType(subBusinessType);
        SheetTypeEnum sheetTypeEnum = paymentSheetTypeEnum.getSheetTypeEnum();
        boolean redFlag = false;
        if (Objects.equals(sheetTypeEnum, SheetTypeEnum.RED_PREPAYMENT)) {
            redFlag = true;
            Double amount = dataList.getDouble(PaymentSheetEnum.AMOUNT.getAttr());
            //金额置为负数
            dataList.put(PaymentSheetEnum.AMOUNT.getAttr(), Arith.mul(amount, -1));
        }
        //添加预收款余额
        saasPaymentSheetHelper.saveByPaymentSheet(paymentSheetEntityExt, distributorMark);
        Long accountId = FastJsonHelper.getLongOrDefaultFromFormData(dataList, PaymentSheetEnum.FUND_ACCOUNT.getAttr(), 0L);
        Long addTime = paymentSheetEntityExt.getAddTime();
        Long sheetTime = fundHelp.getSheetTime4FundFlow(dataList, PaymentSheetEnum.PAYMENT_TIME.getAttr(), explainMap, addTime);
        Double amount =  FastJsonHelper.getDoubleOrDefaultFromFormData(dataList, PaymentSheetEnum.AMOUNT.getAttr(), 0D);
        //账户余额变动
        payAndPaymentSheetHelp.saveByPaymentSheetOrPaySheet(accountId, amount, corpid);
        //流水表日志记录
        FundAccountFlowEntity fundAccountFlowEntity = new FundAccountFlowEntity(corpid, addTime, paymentSheetEntityExt.getCreatorId(), FundAccountFlowTypeEnum.PAYMENT_SHEET.getCode(), paymentSheetEntityExt.getId(), accountId, sheetTime, amount);
        fundAccountFlowModel.insert(fundAccountFlowEntity);
        //预收款、红冲预收预收款余额类型的回款单团队处理在PaymentSheetServiceImpl中的afterSaveForWorkflow方法，并且没有子回款单的概念，所以这边不进行任何处理

        //按最小纬度进项生成客户对账单
        List<PaasFormDataEntityExt> paymentSheetInsertList = new ArrayList<>();
        paymentSheetInsertList.add(paymentSheetEntityExt);
        //记录客户对账单
        saasCustomerStatementHelper.save(XbbRefTypeEnum.PAYMENT_SHEET.getCode(), explainMap, paymentSheetInsertList, distributorMark);
        PushTypeEnum pushTypeEnum;
        String logMemo;
        String pushTitle;
        String pushContent;
        XbbRefTypeEnum xbbRefTypeEnum;
        if (redFlag) {
            pushTypeEnum = PushTypeEnum.PAYMENT_SHEET_RED_PREPAYMENT_ADD;
            if(Objects.equals(DistributorMarkEnum.DISTRIBUTOR.getCode(),distributorMark)) {
                logMemo = I18nMessageUtil.getMessage(CustomerCommunicateConstant.PAYMENT_SHEET_RED_PREPAYMENT_ADD);
            }else {
                logMemo = I18nMessageUtil.getMessage(CrmLogMemoConstant.DYNAMIC_USER_PAYMENT_SHEET_RED_PREPAYMENT_ADD);
            }
            pushTitle = I18nMessageUtil.getMessage(PaymentPushConstant.PAYMENT_SHEET_RED_PREPAYMENT_ADD_TITLE);
            pushContent = I18nMessageUtil.getMessage(PaymentPushConstant.PAYMENT_SHEET_RED_PREPAYMENT_ADD_CONTENT);
            xbbRefTypeEnum = XbbRefTypeEnum.RED_PREPAYMENT;
        } else {
            pushTypeEnum = PushTypeEnum.PAYMENT_SHEET_PREPAYMENT_ADD;
            if(Objects.equals(DistributorMarkEnum.DISTRIBUTOR.getCode(),distributorMark)) {
                logMemo = I18nMessageUtil.getMessage(CustomerCommunicateConstant.PAYMENT_SHEET_PREPAYMENT_ADD);
            } else {
                logMemo = I18nMessageUtil.getMessage(CrmLogMemoConstant.DYNAMIC_USER_PAYMENT_SHEET_PREPAYMENT_ADD);
            }
            pushTitle = I18nMessageUtil.getMessage(PaymentPushConstant.PAYMENT_SHEET_PREPAYMENT_ADD_TITLE);
            pushContent = I18nMessageUtil.getMessage(PaymentPushConstant.PAYMENT_SHEET_PREPAYMENT_ADD_CONTENT);
            xbbRefTypeEnum = XbbRefTypeEnum.PREPAYMENT;
        }
        createLogAndMessage4Pre(xbbRefTypeEnum, pushTypeEnum, dataList, corpid, userId, paymentSheetEntityExt, logMemo, pushTitle, pushContent, distributorMark);

    }

    /**
     * 为新建预收款、红冲预收款余额2种类型的回款单增加项目日志、消息推送
     * @param xbbRefTypeEnum 类型
     * @param pushTypeEnum 推送类型枚举
     * @param dataList 回款单data
     * @param corpid 公司id
     * @param userId 登录员工
     * @param paymentSheetEntityExt 回款单实体
     * @param logMemo 项目日志内容，@see CustomerCommunicateConstant
     * @param pushTitle 推送标题 @see PaymentPushConstant
     * @param pushContent 推送内容 @see PaymentPushConstant
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private void createLogAndMessage4Pre(XbbRefTypeEnum xbbRefTypeEnum, PushTypeEnum pushTypeEnum, JSONObject dataList, String corpid, String userId, PaymentSheetEntityExt paymentSheetEntityExt, String logMemo, String pushTitle, String pushContent, Integer distributorMark) throws XbbException {
        String customerTitle = XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getName();
        if (Objects.equals(distributorMark, DistributorMarkEnum.DISTRIBUTOR.getCode())) {
            customerTitle = XbbRefTypeEnum.DISTRIBUTOR_MANAGEMENT.getName();
        }
        Long customerId = StringUtil.StringToLong(dataList.getString(PaymentSheetEnum.CUSTOMER_ID.getAttr()));
        List<Long> contractIds = FastJsonHelper.getTransferTypesFromData(dataList, PaymentSheetEnum.CONTRACT.getAttr(), Long.class);
        String customerName = dataList.getString(PaymentSheetEnum.CUSTOMER_NAME_LINK_TEXT.getAttr());
        logMemo = String.format(logMemo, customerTitle, customerName, paymentSheetEntityExt.getSerialNo());
        CustomerDynamicAddDTO customerDynamicAddDTO = new CustomerDynamicAddDTO();
        customerDynamicAddDTO.setCorpid(corpid);
        customerDynamicAddDTO.setUserId(userId);
        customerDynamicAddDTO.setCustomerId(customerId);
        customerDynamicAddDTO.setContractIds(contractIds);
        customerDynamicAddDTO.setCustomerName(customerName);
        if (Objects.equals(distributorMark, DistributorMarkEnum.DISTRIBUTOR.getCode())) {
            customerDynamicAddDTO.setDistributorMark(distributorMark);
        }
        customerDynamicAddDTO.setMemo(logMemo);
        customerDynamicAddDTO.setDataId(paymentSheetEntityExt.getId());
        customerDynamicAddDTO.setLogType(ProjectLogEnum.PAYMENT_CREATE.getSubType());
        customerDynamicAddDTO.setCommunicateBusinessText(paymentSheetEntityExt.getSerialNo());
        //预收款打开也要用回款单的702
        customerDynamicAddDTO.setCommunicateBusinessType(XbbRefTypeEnum.PAYMENT_SHEET.getCode());
        customerDynamicAddDTO.setPlatform(PlatFormEnum.INTERNAL.getValue());
        customerCommunicateService.addCustomerDynamic(customerDynamicAddDTO);
        // 回款单创建消息推送
        Long dataId = paymentSheetEntityExt.getId();
        UserEntity userEntity = userModel.getByKeyIngoreDel(paymentSheetEntityExt.getCreatorId(), paymentSheetEntityExt.getCorpid());
        if (Objects.nonNull(userEntity)) {
            List<String> pushUserList = pushHelper.getUserIdListByPushSetRule(corpid, pushTypeEnum.getCode(), pushTypeEnum.getSubCode(), userEntity, paymentSheetEntityExt);
            PushRefTypePojo.Options options = new PushRefTypePojo.Options(paymentSheetEntityExt.getAppId(), paymentSheetEntityExt.getMenuId(), paymentSheetEntityExt.getFormId(), dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.PAYMENT_SHEET.getCode(), XbbRefTypeEnum.PAYMENT_SHEET.getCode());
            MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(dataId), 0, null, pushTitle, format(pushContent, userEntity.getName(), customerName), null, options);
            messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, pushTypeEnum);
        }
    }

    /**
     * 工作流已核销、预收款核销回款单处理
     *
     * @param workflowTransferPOJO
     * @param saasNeedRedundantAttrPojo
     */
    private void workFlowWriteOffSave(WorkflowTransferPOJO workflowTransferPOJO, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) throws XbbException {
        Data pojoData = workflowTransferPOJO.getData();
        Integer subBusinessType = pojoData.getSubBusinessType();
        String corpid = workflowTransferPOJO.getCorpid();
        Long dataId = pojoData.getId();
        JSONObject data = pojoData.getData();
        Long formId = pojoData.getFormId();
        String userId = workflowTransferPOJO.getUser().getUserId();
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
        Integer distributorMark = paasFormExplainEntity.getDistributorMark();
        PaymentSheetEntityExt paymentSheetEntityExt = paymentSheetModel.getByKey(dataId, corpid);

        PaymentSheetTypeEnum paymentSheetTypeEnum = PaymentSheetTypeEnum.getByBusinessType(subBusinessType);
        SheetTypeEnum sheetTypeEnum = paymentSheetTypeEnum.getSheetTypeEnum();
        SheetAttrPojo sheetAttrPojo = new SheetAttrPojo(XbbRefTypeEnum.PAYMENT_SHEET);
        //释放需要回滚信用流水
        boolean creditRollBack = false;
        //回款单的实收回款金额
        Double sheetAmount;
        double allAmount = 0D;
        boolean writeOffPrepaymentFlag = SheetTypeEnum.onlyWriteOffAmount(paymentSheetTypeEnum.getCode());
        Set<Long> contractIds = new HashSet<>();
        Set<Long> paymentIds = new HashSet<>();
        if (writeOffPrepaymentFlag) {
            //预收款核销，是用的核销金额
            sheetAmount = FastJsonHelper.getDoubleOrDefaultFromFormData(data, PaymentSheetEnum.WRITE_OFF_AMOUNT.getAttr(), 0D);
        } else {
            sheetAmount = FastJsonHelper.getDoubleOrDefaultFromFormData(data, PaymentSheetEnum.AMOUNT.getAttr(), 0D);
        }
        List<PaymentSheetEntityExt> sonSheetList = null;
        //应收款和合同对应的回款金额
        Map<Long, Double> contractIdToAmount = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, Double> paymentIdToAmount = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

        //处理回款单金额明细
        SaasFormSaveDTO saasFormSaveDTO = new SaasFormSaveDTO();
        saasFormSaveDTO.setExplainMap(explainMap);
        saasFormSaveDTO.setDistributorMark(paasFormExplainEntity.getDistributorMark());
        List<JSONObject> sonPaymentSheetDataList = saasSaveHelper.handleAmountDetail(saasFormSaveDTO, sheetAmount, sheetTypeEnum,
                sheetAttrPojo, data, saasNeedRedundantAttrPojo.getAmountDetail(), allAmount, contractIdToAmount, paymentIdToAmount, contractIds,
                paymentIds);
        //处理应收款信息
        HandleLinkInfoVO paymentLinkInfoVO = saasPaymentHelper.handlePayment(paymentSheetTypeEnum, data, corpid, paymentIdToAmount, paymentIds);
        List<UpdateDataEntity> updatePayList = paymentLinkInfoVO.getUpdateList();
        //处理合同信息
        List<UpdateDataEntity> updateConList = contractHelp.handleContract(distributorMark, paymentSheetTypeEnum, corpid, contractIdToAmount, contractIds);
        //插入回款单子回款单
        sonSheetList = saasPaymentSheetHelper.savePaymentSheetSon(corpid, sonPaymentSheetDataList,  paymentSheetEntityExt, paymentSheetEntityExt.getUuid(), paymentLinkInfoVO);
        //更新应收款/合同
        paymentModel.savePaymentPlan(corpid, updatePayList);
        contractHelp.saveContract(corpid, updateConList, "PaymentSheetServiceImpl.normalSave：新建已核销回款单更新合同时失败");
        if (writeOffPrepaymentFlag) {
            //核销预收款回款单新建时，减少预收款余额
            saasPaymentSheetHelper.saveByPaymentSheet(paymentSheetEntityExt, distributorMark);
        }else {
            Long addTime = paymentSheetEntityExt.getAddTime();
            Long accountId = FastJsonHelper.getLongOrDefaultFromFormData(data, PaymentSheetEnum.FUND_ACCOUNT.getAttr(), 0L);
            Long sheetTime = fundHelp.getSheetTime4FundFlow(data, PaymentSheetEnum.PAYMENT_TIME.getAttr(), explainMap, addTime);
            //账户余额变动
            payAndPaymentSheetHelp.saveByPaymentSheetOrPaySheet(accountId, sheetAmount, corpid);
            //流水表日志记录
            FundAccountFlowEntity fundAccountFlowEntity = new FundAccountFlowEntity(corpid, addTime, paymentSheetEntityExt.getCreatorId(), FundAccountFlowTypeEnum.PAYMENT_SHEET.getCode(), dataId, accountId, sheetTime, sheetAmount);
            fundAccountFlowModel.insert(fundAccountFlowEntity);
        }
        //按最小纬度进项生成客户对账单
        if (sonSheetList.size() > BasicConstant.ONE) {
            saasCustomerStatementHelper.save(XbbRefTypeEnum.PAYMENT_SHEET.getCode(), explainMap, sonSheetList, distributorMark);
        } else {
            saasCustomerStatementHelper.save(XbbRefTypeEnum.PAYMENT_SHEET.getCode(), explainMap, Arrays.asList(paymentSheetEntityExt), distributorMark);
        }
        //处理回款单团队-必须在团队保存后执行，需要用到回款单的id
        try{
            TeamSavePojo teamSavePojo = new TeamSavePojo(paymentSheetEntityExt, sonSheetList, true, paymentSheetEntityExt, saasNeedRedundantAttrPojo, null, true);
            paymentSheetService.operateSheetTeam(teamSavePojo.getPaymentSheetEntityExt(), teamSavePojo.getSheetList(), teamSavePojo.getIgnoreMainSheet(), teamSavePojo.getNewPaasFormDataEntity(), teamSavePojo.getSaasNeedRedundantAttrPojo(), teamSavePojo.getIsImport(), teamSavePojo.getWorkflowTag());
        }catch (Exception e){
            log.error("处理回款单团队", e);
        }
        if (Objects.equals(distributorMark, DistributorMarkEnum.DISTRIBUTOR.getCode())) {
            Long distributorId = data.getLong(PaymentSheetDistributorEnum.DISTRIBUTOR_ID.getAttr());
            String distributorName = data.getString(PaymentSheetDistributorEnum.DISTRIBUTOR_NAME_LINK_TEXT.getAttr());
            if (!contractIds.isEmpty()) {
                if (Objects.equals(paymentSheetTypeEnum, PaymentSheetTypeEnum.WRITE_OFF)) {
                    // 回款单直接生成流水 > 该订货单有信用流水时，回款单用来还信用，即释放信用
                    List<Long> creditOrderIds = saasCreditHelper.filterCreditOrderIds(new ArrayList<>(contractIds), corpid);
                    if (creditOrderIds.size() > 0) {
                        creditRollBack = true;
                        Double creditOrderAmount = 0D;
                        for (Long creditOrderId : creditOrderIds) {
                            creditOrderAmount = Arith.add(creditOrderAmount, contractIdToAmount.getOrDefault(creditOrderId, 0D));
                        }
                        CreditCardBillInfoPojo infoPojo = new CreditCardBillInfoPojo(CreditCardBillTypeEnum.PAYMENT_SHEET.getCode(), dataId, paymentSheetEntityExt.getSerialNo(), creditOrderAmount, distributorId, distributorName, XbbRefTypeEnum.PAYMENT_SHEET.getCode());
                        CreditCardBillDTO creditCardBillDTO = new CreditCardBillDTO(Arrays.asList(infoPojo));
                        BeanUtil.copyProperties(saasFormSaveDTO, creditCardBillDTO);
                        saasCreditHelper.addBatchCreditCardBill(creditCardBillDTO);
                    }
                } else if (Objects.equals(paymentSheetTypeEnum, PaymentSheetTypeEnum.WRITE_OFF_PREPAYMENT)) {
                    //预收款核销生成信用流水
                    BigDecimal bigDecimal = saasCreditHelper.calcCreditPayLimit(distributorId, new ArrayList<>(contractIds), new ArrayList<>(paymentIds), corpid);
                    if (bigDecimal.compareTo(BigDecimal.ZERO) > 0) {
                        creditRollBack = true;
                        CreditCardBillInfoPojo infoPojo = new CreditCardBillInfoPojo(CreditCardBillTypeEnum.PAYMENT_SHEET.getCode(), dataId, paymentSheetEntityExt.getSerialNo(), bigDecimal.doubleValue(), distributorId, distributorName, XbbRefTypeEnum.PAYMENT_SHEET.getCode());
                        CreditCardBillDTO creditCardBillDTO = new CreditCardBillDTO(Arrays.asList(infoPojo));
                        BeanUtil.copyProperties(saasFormSaveDTO, creditCardBillDTO);
                        DistributorBaseInfoEntity distributorBaseInfoEntity = null;
                        if (Objects.nonNull(distributorBaseInfoEntity)) {
                            creditCardBillDTO.setUserId(distributorBaseInfoEntity.getDistributorUserId().toString());
                            creditCardBillDTO.setLoginUserName(distributorBaseInfoEntity.getDistributorUserName());
                            infoPojo.setCreatorIsDistributor(BasicConstant.ONE);
                        }
                        saasCreditHelper.addBatchCreditCardBill(creditCardBillDTO);
                    }
                }
            }
        }
        // 添加项目日志，及推送消息
        PaymentSheetSaveDTO paymentSheetSaveDTO = new PaymentSheetSaveDTO();
        BeanUtil.copyProperties(saasFormSaveDTO, paymentSheetSaveDTO);
        if(Objects.equals(DistributorMarkEnum.DISTRIBUTOR.getCode(),distributorMark)) {
            createLogAndMessage(PushTypeEnum.PAYMENT_SHEET_ADD, data, corpid, userId, paymentSheetEntityExt, I18nMessageUtil.getMessage(CustomerCommunicateConstant.PAYMENT_SHEET_ADD_CONTRACT), I18nMessageUtil.getMessage(PaymentPushConstant.PAYMENT_SHEET_ADD_TITLE), I18nMessageUtil.getMessage(PaymentPushConstant.PAYMENT_SHEET_ADD_CONTENT), distributorMark);
        } else {
            createLogAndMessage(PushTypeEnum.PAYMENT_SHEET_ADD, data, corpid, userId, paymentSheetEntityExt, I18nMessageUtil.getMessage(CrmLogMemoConstant.DYNAMIC_USER_PAYMENT_SHEET_ADD_CONTRACT), I18nMessageUtil.getMessage(PaymentPushConstant.PAYMENT_SHEET_ADD_TITLE), I18nMessageUtil.getMessage(PaymentPushConstant.PAYMENT_SHEET_ADD_CONTENT), distributorMark);
        }
    }

    /**
     * 为新建已核销、预收款核销、红冲已核销、红冲预收款核销、坏账5种类型的回款单增加项目日志、消息推送
     * @param pushTypeEnum 推送类型枚举
     * @param dataList 回款单data
     * @param corpid 公司id
     * @param userId 登录员工
     * @param paymentSheetEntityExt 回款单实体
     * @param logMemo 项目日志内容，@see CustomerCommunicateConstant
     * @param pushTitle 推送标题 @see PaymentPushConstant
     * @param pushContent 推送内容 @see PaymentPushConstant
     * @param distributorMark 经销商标识
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private void createLogAndMessage(PushTypeEnum pushTypeEnum, JSONObject dataList, String corpid, String userId, PaymentSheetEntityExt paymentSheetEntityExt, String logMemo, String pushTitle, String pushContent, Integer distributorMark) throws XbbException {
        String contractTitle = XbbRefTypeEnum.CONTRACT.getName();
        if (Objects.equals(distributorMark, DistributorMarkEnum.DISTRIBUTOR.getCode())) {
            contractTitle = XbbRefTypeEnum.ORDER.getName();
        }
        // 添加项目日志
        JSONArray contractNoArr = dataList.getJSONArray(PaymentSheetEnum.CONTRACT_LINK_TEXT.getAttr());
        List<String> contractNoList = contractNoArr == null ? new ArrayList<>() : contractNoArr.toJavaList(String.class);
        //逗号分隔的合同编号字符串
        String contractNos = join(SymbolConstant.COMMA_ENGLISH, contractNoList);
        //logMemo需要拼上合同编号
        String communicateMemo = format(logMemo, contractTitle, contractNos, paymentSheetEntityExt.getSerialNo());
        try{
            CustomerDynamicAddDTO customerDynamicAddDTO = new CustomerDynamicAddDTO();
            customerDynamicAddDTO.setCorpid(corpid);
            customerDynamicAddDTO.setUserId(userId);
            customerDynamicAddDTO.setCustomerId(StringUtil.StringToLong(dataList.getString(PaymentSheetEnum.CUSTOMER_ID.getAttr())));
            customerDynamicAddDTO.setContractIds(FastJsonHelper.getTransferTypesFromData(dataList, PaymentSheetEnum.CONTRACT.getAttr(), Long.class));
            customerDynamicAddDTO.setCustomerName(dataList.getString(PaymentSheetEnum.CUSTOMER_NAME_LINK_TEXT.getAttr()));
            if (Objects.equals(distributorMark, DistributorMarkEnum.DISTRIBUTOR.getCode())) {
                customerDynamicAddDTO.setDistributorMark(distributorMark);
            }
            customerDynamicAddDTO.setMemo(communicateMemo);
            customerDynamicAddDTO.setCommunicateBusinessText(paymentSheetEntityExt.getSerialNo());
            customerDynamicAddDTO.setCommunicateBusinessType(XbbRefTypeEnum.PAYMENT_SHEET.getCode());
            customerDynamicAddDTO.setDataId(paymentSheetEntityExt.getId());
            customerDynamicAddDTO.setLogType(ProjectLogEnum.PAYMENT_CREATE.getSubType());
            customerDynamicAddDTO.setPlatform(PlatFormEnum.INTERNAL.getValue());
            customerCommunicateService.addCustomerDynamic(customerDynamicAddDTO);
        }catch (Exception e){
            log.error("回款单增加项目日志", e);
        }
        // 回款单创建消息推送
        Long dataId = paymentSheetEntityExt.getId();
        UserEntity userEntity = userModel.getByKeyIngoreDel(paymentSheetEntityExt.getCreatorId(), paymentSheetEntityExt.getCorpid());
        if (Objects.nonNull(userEntity)) {
            List<String> pushUserList = pushHelper.getUserIdListByPushSetRule(corpid, pushTypeEnum.getCode(), pushTypeEnum.getSubCode(), userEntity, paymentSheetEntityExt);
            PushRefTypePojo.Options options = new PushRefTypePojo.Options(paymentSheetEntityExt.getAppId(), paymentSheetEntityExt.getMenuId(), paymentSheetEntityExt.getFormId(), dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.PAYMENT_SHEET.getCode(), XbbRefTypeEnum.PAYMENT_SHEET.getCode());
            MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(dataId), 0, null, pushTitle, format(pushContent, userEntity.getName(), contractNos), null, options);
            messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, pushTypeEnum);
        }
    }

    @Override
    public void update(WorkflowTransferPOJO workflowTransferPOJO, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) throws XbbException {
        // 文件柜
        saveDataCabinetFile(workflowTransferPOJO);

        String corpid = workflowTransferPOJO.getCorpid();
        Data pojoData = workflowTransferPOJO.getData();
        JSONObject data = pojoData.getData();


        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(pojoData.getFormId(), corpid);
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains());

        //更新子单信息
        // TODO 加了经销商标识，需要核对
        SheetTypeEnum sheetTypeEnum = SheetTypeEnum.getByCodeRefTypeEnum(data.getString(PaymentSheetEnum.PAYMENT_SHEET_TYPE.getAttr()), XbbRefTypeEnum.PAYMENT_SHEET);
        List<UpdateDataEntity> updateList = payAndPaymentSheetHelp.updateSonDataList4Sheet(corpid, sheetTypeEnum, paasFormExplainEntity.getDistributorMark(), saasNeedRedundantAttrPojo.getAmountDetail(), explainMap);
        if (CollectionsUtil.isNotEmpty(updateList)) {
            paymentSheetModel.updateBatch(updateList, corpid);
        }

        // api
        apiHook(workflowTransferPOJO);
        // log
        afterUpdateLog(workflowTransferPOJO);
    }

    @Override
    public void updateBack(Long taskId, WorkflowTransferPOJO workflowTransferPOJO) throws XbbException {
        try {
            String corpid = workflowTransferPOJO.getCorpid();
            Long backupDataId = workflowTransferPOJO.getBackupDataId();
            Long dataId = workflowTransferPOJO.getData().getId();
            WorkflowBackupDataEntity workflowBackupDataEntity = workflowBackupDataModel.getByKey(backupDataId, corpid);
            if (Objects.nonNull(workflowBackupDataEntity)) {
                JSONObject data = workflowBackupDataEntity.getData();

                replenishAttrForBackupData(workflowTransferPOJO.getData().getData(), data);

                PaymentSheetEntityExt paymentSheetEntity = new PaymentSheetEntityExt();
                paymentSheetEntity.setId(dataId);
                paymentSheetEntity.setCorpid(corpid);
                paymentSheetEntity.setData(data);
                paymentSheetEntity.setSerialNo(data.getString(FieldTypeEnum.SERIALNO.getAlias()));
                paymentSheetEntity.setOwnerId(getOwnerId(data));
                paymentSheetEntity.setDepartmentId(data.getLong(FieldTypeEnum.DEPARTMENTID.getAlias()));

                FormDataUtil.removeSystemData(data);
                if (Objects.equals(workflowTransferPOJO.getOperate(), WorkflowOperateEnum.UPDATE.getType())) {
                    paymentSheetEntity.setFlowStatus(FlowStatusEnum.PASS.getType());
                }
                paymentSheetModel.update(paymentSheetEntity);
                // 回退被删掉的子表单
                updateBackSubForm(paymentSheetEntity, corpid, IndexTypeEnum.IDX_SAAS_PAYMENT_SHEET_SUB);
                //回退被删掉的富文本
                updateBackRichText(taskId, workflowTransferPOJO);
            }
        } catch (Exception e) {
            LOGGER.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowPaymentSheetStrategy.updateBack", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    @Override
    public void approvalFailed(Long taskId, WorkflowTransferPOJO workflowTransferPOJO, Integer taskType) throws XbbException {
        try {
            String corpid = workflowTransferPOJO.getCorpid();
            Data workflowData = workflowTransferPOJO.getData();
            Long dataId = workflowData.getId();
            Long formId = workflowData.getFormId();
            Integer businessType = workflowData.getBusinessType();
            Integer saasMark = workflowData.getSaasMark();
            PaymentSheetEntityExt paymentSheetEntityExt = new PaymentSheetEntityExt();
            paymentSheetEntityExt.setId(dataId);
            if (Objects.equals(TaskTypeEnum.REVOKE.getType(), taskType)) {
                paymentSheetEntityExt.setFlowStatus(FlowStatusEnum.REVOKE.getType());
            } else {
                paymentSheetEntityExt.setFlowStatus(FlowStatusEnum.REJECT.getType());
            }
            paymentSheetEntityExt.setCorpid(corpid);
            paymentSheetEntityExt.setUpdateTime(DateTimeUtil.getInt());
            paymentSheetModel.update(paymentSheetEntityExt);
            // 子表单
            DelEnum del = DelEnum.APPROVE_FAILED;

            paasFormSubDataModel.deleteBatchByDataId(Collections.singletonList(dataId), corpid, IndexTypeEnum.IDX_SAAS_PAYMENT_SHEET_SUB, del);
            //富文本
            deleteFormRichText(dataId, corpid, formId, businessType, saasMark, DelEnum.NORMAL);

            // 团队
            List<PaymentSheetUserEntity> paymentSheetUserEntities = paymentSheetUserModel.getPaymentSheetUserIdList(corpid, dataId, null);
            if (CollectionsUtil.isNotEmpty(paymentSheetUserEntities)) {
                paymentSheetUserModel.deleteBatchUser(corpid, paymentSheetUserEntities, del.getDel());
            }
            /*List<ContractUserEntity> contractUserList = contractUserModel.getContractUserList(corpid, dataId, null);
            if (CollectionsUtil.isNotEmpty(contractUserList)) {
                contractUserModel.deleteBatchUser(contractUserList, corpid, del.getDel());
            }*/
        } catch (Exception e) {
            LOGGER.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowPaymentSheetStrategy.approvalFailed error ", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }
}
